package bigbeard.tools.thread.pools;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;

/**
 * @author bigbeard on 2018-9-14.
 * <p>
 * 守护线程,通过观察者的方式实现
 */
public class ThreadExitListener implements PropertyChangeListener {

    private static final int MAX_QUEUE_SIZE = 10;
    private static final int CORE_POOL_SIZE = 1;
    private static final int MAX_POOL_SIZE = 1;
    private static final long KEEP_ALIVE_TIME = 0L;
    private static final String THREAD_NAME_PREFIX = "Thread-exit-listener-restart-%s";

    private ExecutorService executorService;
    private ThreadFactoryBuilder threadFactoryBuilder;
    private final ThreadPoolManager manager = new ThreadPoolManager();

    final transient private PropertyChangeSupport listeners = new PropertyChangeSupport(this);


    /**
     * 创建线程是的基本信息
     *
     * @param threadFactoryBuilder 线程创建的信息
     */
    public void setThreadFactoryBuilder(ThreadFactoryBuilder threadFactoryBuilder) {
        this.threadFactoryBuilder = threadFactoryBuilder;
    }

    /**
     * 如果采用线程池执行任务可以将线程池传入进来,
     * 重启任务后还可以在当前的线程池中执行避免线程反复创建
     *
     * @param executorService 执行当前任务的线程池
     */
    public void setExecutorService(ExecutorService executorService) {
        this.executorService = executorService;
    }


    public ThreadExitListener() {
        this.addPropertyChangeListener(this);
    }

    private boolean error=false;

    public void setError(boolean b) {
        error = b;
        firePropertyChange("error", this, error);
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {

        System.out.println(">>>>"+evt.getPropertyName());
        Object o = evt.getOldValue();
        if (!(o instanceof Runnable)) {
            System.out.println("not runnable ");
            return;
        }
        System.out.println(Thread.currentThread().getId()
                + ":" + Thread.currentThread().getName()
                + " thread begin star");

        Runnable runnable = (Runnable) o;
        if (null != executorService) {
            executorService.execute(runnable);
        } else {
            if (null == threadFactoryBuilder) {
                threadFactoryBuilder = new ThreadFactoryBuilder();
                threadFactoryBuilder.setNamePrefix(THREAD_NAME_PREFIX).setDaemon(true);
            }
            executorService = manager
                    .createExecutorService(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME,
                            new ArrayBlockingQueue<>(MAX_QUEUE_SIZE),
                            threadFactoryBuilder.build());
            executorService.execute(runnable);
        }
    }


    public void addPropertyChangeListener(PropertyChangeListener listener) {
        listeners.addPropertyChangeListener(listener);
    }

    protected void firePropertyChange(String prop, Object old, Object newValue) {
        listeners.firePropertyChange(prop, old, newValue);
    }

    public void removePropertyChangeListener(PropertyChangeListener l) {
        listeners.removePropertyChangeListener(l);
    }
}
